package com.zyw.orm.mybatis;

import com.zyw.orm.support.page.Page;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import java.util.Map;
import java.util.Properties;

/**
 * @author zhangyw
 * @date 2017/3/15 10:50
 */
public abstract class BaseInterceptor implements Interceptor {

    Log logger = LogFactory.getLog(getClass());

    static final String PAGE = "page";

    protected static final String DELEGATE = "delegate";

    protected static final String MAPPED_STATEMENT = "mappedStatement";

    private static ObjectFactory objectFactory = new DefaultObjectFactory();
    private static ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
    private static DefaultReflectorFactory reflectorFactory = new DefaultReflectorFactory();

    MetaObject getDelegateMetaObject(Object statementHandler) {
        MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, objectFactory, objectWrapperFactory, reflectorFactory);

        // 分离代理对象链(由于目标类可能被多个拦截器拦截，从而形成多次代理，通过下面的两次循环可以分离出最原始的的目标类)
        while (metaStatementHandler.hasGetter("h")) {
            Object object = metaStatementHandler.getValue("h");
            metaStatementHandler = MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
        }
        // 分离最后一个代理对象的目标类
        while (metaStatementHandler.hasGetter("target")) {
            Object object = metaStatementHandler.getValue("target");
            metaStatementHandler = MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
        }
        return metaStatementHandler;
    }

    Page<Object> convertParameter(Object parameterObject) {
        if (parameterObject instanceof Page) {
            return (Page<Object>) parameterObject;
        } else if (parameterObject instanceof Map) {
            return (Page<Object>) ((Map) parameterObject).get(PAGE);
        } else {
            return null;
        }
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        return null;
    }

    @Override
    public Object plugin(Object target) {
        return null;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
